﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Text;

using Kenly.DBFramework.Reflection;
using Kenly.DBFramework;

namespace Kenly.DBFramework.Gateway
{
    /// <summary>
    /// The gateway to a database view.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract partial class ViewGateway<T>
    {
        /// <summary>
        /// 
        /// </summary>
        public object EntityId
        {
            get
            {
                string identityName = null;
                object identityValue =null;
                IdentityUtility.GetIdentity(this, out identityName, out identityValue);
                return identityValue;
            }
            set
            {
                IdentityUtility.SetIdentityValue(this, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public object PrimaryKey
        {
            get
            {
                string key = null;
                object keyValue =null;
                KeyUtility.GetPrimaryKey(this, out key, out keyValue);
                return keyValue;
            }
            set
            {
                KeyUtility.SetPrimaryKey(this, value);
            }
        }


        #region Common


        /// <summary>
        /// 
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        protected static int Count(string condition)
        {
            string sql = CreateCommandReflector().Count(typeof(T), condition);
            _commandText = sql;
            object obj = CreateCommandExecutor().ExecuteScalar(sql, false);

            return GetIntScalarValue(obj);
        }

        /// <summary>
        /// The row count of the table.
        /// </summary>
        /// <returns></returns>
        protected static int Count()
        {
            return Count(" 1=1 ");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<int> CountGroup(string condition, string groupBy)
        {
            string sql = CreateCommandReflector().CountGroup(typeof(T), condition, groupBy);
            _commandText = sql;

            DataTable dt = new DataTable();
            dt.Locale = CultureInfo.InvariantCulture;

            dt = CreateCommandExecutor().ExecuteDataTable(sql, false);

            int firstColumnIndex = 0;
            List<int> result = new List<int>();
            foreach (DataRow row in dt.Rows)
            {
                result.Add(GetIntScalarValue(row[firstColumnIndex]));
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<int> CountGroup(string groupBy)
        {
            return CountGroup(" 1=1 ", groupBy);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected static double Sum(string columnName)
        {
            return Sum(columnName, " 1=1 ");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        protected static double Sum(string columnName, string condition)
        {
            string sql = CreateCommandReflector().Sum(typeof(T), columnName, condition);
            _commandText = sql;
            object obj = CreateCommandExecutor().ExecuteScalar(sql, false);

            return GetScalarValue(obj);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<double> SumGroup(string columnName, string condition, string groupBy)
        {
            string sql = CreateCommandReflector().SumGroup(typeof(T), columnName, condition, groupBy);
            _commandText = sql;

            DataTable dt = new DataTable();
            dt.Locale = CultureInfo.InvariantCulture;

            dt= CreateCommandExecutor().ExecuteDataTable(sql, false);

            List<double> result = new List<double>();
            foreach (DataRow row in dt.Rows)
            {
                result.Add(GetScalarValue(row[columnName]));
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<double> SumGroup(string columnName, string groupBy)
        {
            return SumGroup(columnName, " 1=1 ", groupBy);
        }

        private static double GetScalarValue(object obj)
        {
            double scalarValue = 0;
            if (obj != null && !(obj is System.DBNull))
            {
                double.TryParse(obj.ToString(), out scalarValue);
            }

            return scalarValue;
        }

        private static int GetIntScalarValue(object obj)
        {
            int scalarValue = 0;
            if (obj != null && !(obj is System.DBNull))
            {
                int.TryParse(obj.ToString(), out scalarValue);
            }

            return scalarValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        protected static object Max(string columnName, string condition)
        {
            string sql = CreateCommandReflector().Max(typeof(T), columnName, condition);
            _commandText = sql;
            object obj = CreateCommandExecutor().ExecuteScalar(sql, false);

            return obj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected static object Max(string columnName)
        {
            return Max(columnName, " 1=1 ");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<object> MaxGroup(string columnName, string condition, string groupBy)
        {
            string sql = CreateCommandReflector().MaxGroup(typeof(T), columnName, condition, groupBy);
            _commandText = sql;

            return MaxMinGroup(columnName, sql);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<object> MaxGroup(string columnName, string groupBy)
        {
            return MaxGroup(columnName, " 1=1 ", groupBy);
        }

        private static List<object> MaxMinGroup(string columnName, string sql)
        {
            DataTable dt = new DataTable();
            dt.Locale = CultureInfo.InvariantCulture;

            dt = CreateCommandExecutor().ExecuteDataTable(sql, false);

            List<object> result = new List<object>();
            foreach (DataRow row in dt.Rows)
            {
                result.Add(row[columnName]);
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        protected static object Min(string columnName, string condition)
        {
            string sql = CreateCommandReflector().Min(typeof(T), columnName, condition);
            _commandText = sql;
            object obj = CreateCommandExecutor().ExecuteScalar(sql, false);

            return obj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected static object Min(string columnName)
        {
            return Min(columnName, " 1=1 ");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="condition"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<object> MinGroup(string columnName, string condition, string groupBy)
        {
            string sql = CreateCommandReflector().MinGroup(typeof(T), columnName, condition, groupBy);
            _commandText = sql;

            return MaxMinGroup(columnName, sql);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="groupBy"></param>
        /// <returns></returns>
        protected static List<object> MinGroup(string columnName, string groupBy)
        {
            return MinGroup(columnName, " 1=1 ", groupBy);
        }

        /// <summary>
        /// Determines whether the entity exists with the specified identity.
        /// </summary>
        /// <returns></returns>
        public bool ExistsById()
        {
            string sql = CreateCommandReflector().ExistsById(this.Entity);
            return ExistsBySql(sql);
        }

        /// <summary>
        /// Determines whether the entity exists with the specified primary key.
        /// </summary>
        /// <returns></returns>
        public bool ExistsByPK()
        {
            string sql = CreateCommandReflector().ExistsByPK(this.Entity);
            return ExistsBySql(sql);
        }

        /// <summary>
        /// Determines whether the entity exists with the specified condition.
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        protected static bool Exists(string condition)
        {
            if (string.IsNullOrEmpty(condition))
            {
                return false;
            }
            string sql = CreateCommandReflector().Exists(typeof(T), condition);
            return ExistsBySql(sql);
        }

        private static bool ExistsBySql(string sql)
        {
            if (string.IsNullOrEmpty(sql))
            {
                return false;
            }
            int count = 0;
            _commandText = sql;
            object obj = CreateCommandExecutor().ExecuteScalar(sql, false);
            //ClearOrder();
            if (obj != null && !(obj is System.DBNull))
            {
                count = Convert.ToInt32(obj, CultureInfo.InvariantCulture);
            }
            return count > 0;
        }



        #endregion  //Common


        #region  Convert

        /// <summary>
        /// Copies the column property values from source to target.
        /// </summary>
        /// <param name="targetEntity"></param>
        public void ShadowCopyTo(T targetEntity)
        {
            EntityUtility.ShadowCopy(targetEntity, this.Entity);
        }

        /// <summary>
        /// Copies the column property values from source to target.
        /// </summary>
        /// <param name="targetEntity"></param>
        public void ShadowCopyTo(object targetEntity)
        {
            EntityUtility.ShadowCopy(targetEntity, this.Entity);
        }

        /// <summary>
        /// Converts a row to an object.
        /// </summary>
        /// <param name="adaptedRow"></param>
        /// <returns></returns>
        public static T ToObject(DataRow adaptedRow)
        {
            return EntityMapper<T>.ToEntity(adaptedRow);
        }

        /// <summary>
        ///  Converts a table to an array of entities.
        /// </summary>
        /// <param name="adaptedTable"></param>
        /// <returns></returns>
        public static List<T> ToObjects(DataTable adaptedTable)
        {
            return EntityMapper<T>.ToEntities(adaptedTable);
        }

        /// <summary>
        /// Converts data rows to an array of entities.
        /// </summary>
        /// <param name="adaptedRows"></param>
        /// <returns></returns>
        public static List<T> ToObjects(DataRowCollection adaptedRows)
        {
            return EntityMapper<T>.ToEntities(adaptedRows);
        }

        /// <summary>
        /// Creates a table each of whose rows is reflected from the entity properties.The state of all rows is Added state.
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static DataTable ToTable(IList<T> entities)
        {
            return EntityMapper<T>.ToTable(entities);
        }

        /// <summary>
        /// Creates a table each of whose rows is reflected from the entity properties.The state of all rows is Added state.
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static DataTable ToTable(params T[] entities)
        {
            return EntityMapper<T>.ToTable(entities);
        }

        /// <summary>
        /// Creates a table each of whose rows is reflected from the entity properties or database columns.The state of all rows is Added state.
        /// </summary>
        /// <param name="isAdapted"></param>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static DataTable ToTable(bool isAdapted, IList<T> entities)
        {
            return EntityMapper<T>.ToTable(entities,isAdapted);
        }

        /// <summary>
        /// Creates a table each of whose rows is reflected from the entity properties or database columns.The state of all rows is Added state.
        /// </summary>
        /// <param name="isAdapted"></param>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static DataTable ToTable(bool isAdapted, params T[] entities)
        {
            return EntityMapper<T>.ToTable(entities,isAdapted);
        }

        /// <summary>
        ///  Creates a list of instances.
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public static List<T> CreateInstances(int count)
        {
            return EntityMapper<T>.CreateEntities(count);
        }

        /// <summary>
        /// Maps property name to column name.
        /// </summary>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static string ToColumnName(string propertyName)
        {
            return EntityMapper<T>.ToColumnName(propertyName);
        }

        /// <summary>
        /// Maps column name to property name.
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static string ToPropertyName(string columnName)
        {
            return EntityMapper<T>.ToPropertyName(columnName);
        }

        #endregion //convert


    }


}